﻿using System.Dynamic;
using System.Reflection;
using ApiLib.Models;
using SqlSugar;

namespace ApiLib.Utils;

/// <summary>
/// SqlSugarUtil
/// </summary>
public static class SqlSugarUtil
{
    /// <summary>
    /// 查询单个对象转集合
    /// </summary>
    /// <param name="queryable"></param>
    /// <returns></returns>
    public static IDictionary<string, object?>? ToDictionary(this ISugarQueryable<object> queryable)
    {
        var first = queryable.First();
        if (first is ExpandoObject expandoObject)
        {
            return expandoObject;
        }

        return default;
    }

    /// <summary>
    /// 分页
    /// </summary>
    /// <param name="queryable"></param>
    /// <param name="param"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static ListResponse<T> ToPageList<T>(this ISugarQueryable<T> queryable, PageParam param)
    {
        var totalCount = 0;
        var pageList = queryable.ToPageList(param.PageIndex, param.PageSize, ref totalCount);
        return new ListResponse<T> { List = pageList, TotalCount = totalCount };
    }

    /// <summary>
    /// 复制一份
    /// </summary>
    /// <param name="queryable"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static ISugarQueryable<T> New<T>(this ISugarQueryable<T> queryable)
    {
        return queryable.Clone();
    }

    /// <summary>
    /// 获取数据库名称
    /// </summary>
    /// <param name="config"></param>
    /// <returns></returns>
    public static string GetDbName(this ConnectionConfig config)
    {
        switch (config.DbType)
        {
            case DbType.MySql or DbType.SqlServer or DbType.PostgreSQL:
            {
                var dbPres = new[] { "Database=", "DATABASE=", "database=" };
                var dbConfigs = config.ConnectionString.Split(";");
                foreach (var dbConfig in dbConfigs)
                {
                    foreach (var dbPre in dbPres)
                    {
                        if (dbConfig.Contains(dbPre))
                        {
                            return dbConfig.Replace(dbPre, "");
                        }
                    }
                }

                break;
            }
            case DbType.Oracle:
                var oracleStr = config.ConnectionString.Split(";").FirstOrDefault(s => s.Contains("Data Source="));
                if (!string.IsNullOrEmpty(oracleStr))
                {
                    return oracleStr.Substring(oracleStr.IndexOf("/", StringComparison.Ordinal) + 1);
                }

                break;
        }

        return config.ConfigId as string ?? "Null";
    }

    /// <summary>
    /// 解析为SqlSugar对象
    /// </summary>
    /// <param name="expandoObjects"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    public static List<object> SugarParseToObj(this IEnumerable<ExpandoObject> expandoObjects, Type type)
    {
        var list = new List<object>();
        foreach (var expandoObject in expandoObjects)
        {
            var obj = expandoObject.SugarParseToObj(type);
            if (obj != null)
            {
                list.Add(obj);
            }
        }

        return list;
    }

    /// <summary>
    /// 解析为SqlSugar对象
    /// </summary>
    /// <param name="expandoObject"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    public static object? SugarParseToObj(this ExpandoObject expandoObject, Type type)
    {
        IDictionary<string, object?> dictionary = expandoObject;
        var properties = type.GetProperties();
        foreach (var property in properties)
        {
            if (dictionary.TryGetValue(property.Name, out var obj)
                && obj != null
                && !string.IsNullOrEmpty(obj.ToString()))
            {
                continue;
            }

            if (property.GetCustomAttribute(typeof(SugarColumn), true) is SugarColumn attribute)
            {
                dictionary[property.Name] = dictionary.TryGetValue(attribute.ColumnName, out var val) ? val : "";
            }
        }

        return dictionary.CastToObj(type);
    }
}